package com.leyou.search.service.impl;

import com.leyou.common.dto.PageDTO;
import com.leyou.item.client.ItemClient;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpecParamDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.search.entity.Goods;
import com.leyou.search.repository.GoodsRepository;
import com.leyou.search.service.IndexService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class IndexServiceImpl implements IndexService {

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private GoodsRepository goodsRepository;

    @Override
    public Goods buildGoods(SpuDTO spuDTO) {

        // 1.自动补全的提示字段
        ArrayList<String> suggestion = new ArrayList<>();

        suggestion.add(spuDTO.getName());

        String brandName = spuDTO.getBrandName();

        suggestion.add(brandName);

        String categoryName = spuDTO.getCategoryName().split("/")[2];

        suggestion.add(categoryName);

        // 对brandName中的中文的括号（）进行去除操作
//        int subLength = brandName.indexOf("（") == -1 ? brandName.length() : brandName.indexOf("（");
//
//        String shortBrandName = brandName.substring(0,subLength);

        // 只对组合补全进行去括号操作
        String shortBrandName = StringUtils.substringBefore(brandName, "（");

        // 输入 分类+品牌 以及 品牌+分类 都可以出现 可以识别自动补全
        suggestion.add(categoryName + shortBrandName);

        suggestion.add(shortBrandName + categoryName);

        // 2.sku的价格集合
        // 2.1查询sku集合
        List<SkuDTO> skus = spuDTO.getSkus();

        if (CollectionUtils.isEmpty(skus)) {

            // 没有sku，去查询sku的集合
            skus = itemClient.querySkuBySpuId(spuDTO.getBrandId());

        }

        // 2.获取价格集合
        Set<Long> prices = skus.stream().map(SkuDTO::getPrice).collect(Collectors.toSet());

        // 3.商品销量
        long sold = skus.stream().mapToLong(SkuDTO::getSold).sum();

        // 4. 获取sku的图片

        String image = StringUtils.substringBefore(skus.get(0).getImages(), ",");

        // 5.规格参数
        List<Map<String,Object>> specs = new ArrayList<>();

        // 5.1.查询规格参数name和value键值对，只查询参与搜索的
        List<SpecParamDTO> specParamDTOS = this.itemClient.querySpecsValues(spuDTO.getId(), true);

        // 5.2.封装
        for (SpecParamDTO specParamDTO : specParamDTOS) {

            Map<String,Object> spec = new HashMap<>(2);

            spec.put("name",specParamDTO.getName());

            spec.put("value",chooseSegment(specParamDTO));

            specs.add(spec);

        }

        // 创建Goods对象，并封装数据
        Goods goods = new Goods();

        goods.setUpdateTime(new Date());

        // 自动补全的提示字段
        goods.setSuggestion(suggestion);

        // 规格参数
        goods.setSpecs(specs);

        // 商品销量
        goods.setSold(sold);

        // 商品标题
        goods.setTitle(spuDTO.getTitle() + StringUtils.join(suggestion + " "));

        // sku的价格集合
        goods.setPrices(prices);

        // sku的某个图片
        goods.setImage(image);

        goods.setCategoryId(spuDTO.getCid3());

        goods.setBrandId(spuDTO.getBrandId());

        goods.setId(spuDTO.getId());

        return goods;

    }

    @Override
    public void loadData() {

        // 删除已经存在的索引库
        try {
            goodsRepository.deleteIndex();
        } catch (Exception e) {
        }

        // 然后创建一个新的
        goodsRepository.createIndex("{\n" +
                "  \"settings\": {\n" +
                "    \"analysis\": {\n" +
                "      \"analyzer\": {\n" +
                "        \"my_pinyin\": {\n" +
                "          \"tokenizer\": \"ik_smart\",\n" +
                "          \"filters\": [\n" +
                "            \"py\"\n" +
                "          ]\n" +
                "        }\n" +
                "      },\n" +
                "      \"filters\": {\n" +
                "        \"py\": {\n" +
                "\t\t  \"type\": \"pinyin\",\n" +
                "          \"keep_full_pinyin\": true,\n" +
                "          \"keep_joined_full_pinyin\": true,\n" +
                "          \"keep_original\": true,\n" +
                "          \"limit_first_letter_length\": 16,\n" +
                "          \"remove_duplicated_term\": true\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  },\n" +
                "  \"mappings\": {\n" +
                "    \"properties\": {\n" +
                "      \"id\": {\n" +
                "        \"type\": \"keyword\"\n" +
                "      },\n" +
                "      \"suggestion\": {\n" +
                "        \"type\": \"completion\",\n" +
                "        \"analyzer\": \"my_pinyin\",\n" +
                "        \"search_analyzer\": \"ik_smart\"\n" +
                "      },\n" +
                "      \"title\":{\n" +
                "        \"type\": \"text\",\n" +
                "        \"analyzer\": \"my_pinyin\",\n" +
                "        \"search_analyzer\": \"ik_smart\"\n" +
                "      },\n" +
                "      \"image\":{\n" +
                "        \"type\": \"keyword\",\n" +
                "        \"index\": false\n" +
                "      },\n" +
                "      \"updateTime\":{\n" +
                "        \"type\": \"date\"\n" +
                "      },\n" +
                "      \"specs\":{\n" +
                "        \"type\": \"nested\",\n" +
                "        \"properties\": {\n" +
                "          \"name\":{\"type\": \"keyword\" },\n" +
                "          \"value\":{\"type\": \"keyword\" }\n" +
                "        }\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}");

        //获取到spu，转换为goods，最终保存

        int page = 1, rows = 100;

        while (true) {

            log.info("开始导入第{}页数据",page);

            PageDTO<SpuDTO> spuDTOPageDTO = itemClient.querySpuByPage(page, rows, true, null, null, null);

            // 没有数据结束
            if (spuDTOPageDTO.getTotalPage() == 0) {

                break;

            }

            List<SpuDTO> spuDTOS = spuDTOPageDTO.getItems();

            List<Goods> goodsList = spuDTOS.stream().map(this::buildGoods).collect(Collectors.toList());

            this.goodsRepository.saveAll(goodsList);

            log.info("导入第{}页结束",page);

            page++;

            // 下一页不存在则停止
            Long totalPage = spuDTOPageDTO.getTotalPage();

            if (page > totalPage) {

                break;

            }

        }

    }

    @Override
    public void saveGoodsById(Long spuId) {

        // spuDTO ==> goods

        // 根据spuId查询对应的spu对象
        List<SpuDTO> items = this.itemClient.querySpuByPage(null, null, null, null, null, spuId).getItems();

        // 当值存在时把spuDTO转换为goods然后保存
        if (!CollectionUtils.isEmpty(items)) {

            this.goodsRepository.save(buildGoods(items.get(0)));

        }

    }

    @Override
    public void deleteGoodsById(Long spuId) {

        this.goodsRepository.deleteById(spuId);

    }

    private Object chooseSegment(SpecParamDTO specParamDTO) {

        Object value = specParamDTO.getValue();

        if (value == null || StringUtils.isBlank(value.toString())) {

            return "其他";

        }

        if (!specParamDTO.getNumeric() || StringUtils.isBlank(specParamDTO.getSegments()) || value instanceof Collection) {

            return value;

        }

        double val = parseDouble(value.toString());

        String result = "其它";

        // 保存数值段
        for (String segment : specParamDTO.getSegments().split(",")) {

            String[] split = segment.split("-");

            // 获取数值范围

            double begin = parseDouble(split[0]);

            double end = Double.MAX_VALUE;

            if (split.length == 2) {

                end = parseDouble(split[1]);

            }

            // 判断是否在范围内
            if (val >= begin && val < end) {

                if (split.length == 1) {

                    result = split[0] + specParamDTO.getUnit() + "以上";

                } else if (begin == 0) {

                    result = split[1] + specParamDTO.getUnit() + "以下";

                } else {

//                    result = split[0] + specParamDTO.getUnit() + "以上，" + split[1] + specParamDTO.getUnit() + "以下";

                    result = segment + specParamDTO.getUnit();

                }

                break;

            }

        }

        return result;
    }

    private double parseDouble(String str) {

        try {

            return Double.parseDouble(str);

        } catch (NumberFormatException e) {

            return 0;

        }

    }
}
